﻿using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.ComponentModel;
using System.IO;
using System.Text;

namespace Rage
{
    public class GemmingTemplate : INotifyPropertyChanged
    {
        [XmlElement("Id")]
        public string _id;
        [XmlIgnore]
        public string Id
        {
            get { return _id; }
            set { _id = value; }
        }

        [XmlElement("Model")]
        public string _model;
        [XmlIgnore]
        public string Model
        {
            get { return _model; }
            set { _model = value; }
        }

        [XmlElement("Enabled")]
        public bool _enabled;
        [XmlIgnore]
        public bool Enabled
        {
            get { return _enabled; }
            set 
            {
                if (_enabled != value)
                {
                    _enabled = value;
                    OnPropertyChanged("Enabled");
                }
            }
        }

        [XmlElement("Group")]
        public string _group;
        [XmlIgnore]
        public string Group
        {
            get { return _group; }
            set { _group = value; }
        }

        [XmlElement("AmoringId")]
        public string _armoringId;
        [XmlIgnore]
        public string ArmoringId
        {
            get { return _armoringId ?? (_armoringId = "0"); }
            set { _armoringId = value; }
        }

        [XmlIgnore]
        private Item _armoring;
        [XmlIgnore]
        public Item Armoring
        {
            get
            {
                if (ArmoringId == "0") return null;
                if (_armoring == null || _armoring.Id != ArmoringId)
                {
                    _armoring = Item.LoadFromId(ArmoringId, false, true, true, false);
                }
                return _armoring;
            }
            set
            {
                if (value == null)
                    ArmoringId = "0";
                else
                    ArmoringId = value.Id;
                _armoring = value;
                OnPropertyChanged("Armoring");
            }
        }

        [XmlElement("BarrelId")]
        public string _barrelId;
        [XmlIgnore]
        public string BarrelId
        {
            get { return _barrelId ?? (_barrelId = "0"); }
            set { _barrelId = value; }
        }

        [XmlIgnore]
        private Item _barrel;
        [XmlIgnore]
        public Item Barrel
        {
            get
            {
                if (BarrelId == "0") return null;
                if (_barrel == null || _barrel.Id != BarrelId)
                {
                    _barrel = Item.LoadFromId(BarrelId, false, true, true, false);
                }
                return _barrel;
            }
            set
            {
                if (value == null)
                    BarrelId = "0";
                else
                    BarrelId = value.Id;
                _barrel = value;
                OnPropertyChanged("Barrel");
            }
        }

        [XmlElement("HiltId")]
        public string _hiltId;
        [XmlIgnore]
        public string HiltId
        {
            get { return _hiltId ?? (_hiltId = "0"); }
            set { _hiltId = value; }
        }

        [XmlIgnore]
        private Item _hilt;
        [XmlIgnore]
        public Item Hilt
        {
            get
            {
                if (HiltId == "0") return null;
                if (_hilt == null || _hilt.Id != HiltId)
                {
                    _hilt = Item.LoadFromId(HiltId, false, true, true, false);
                }
                return _hilt;
            }
            set
            {
                if (value == null)
                    HiltId = "0";
                else
                    HiltId = value.Id;
                _hilt = value;
                OnPropertyChanged("Hilt");
            }
        }

        [XmlElement("ModId")]
        public string _modId;
        [XmlIgnore]
        public string ModId
        {
            get { return _modId ?? (_modId = "0"); }
            set { _modId = value; }
        }

        [XmlIgnore]
        private Item _mod;
        [XmlIgnore]
        public Item Mod
        {
            get
            {
                if (ModId == "0") return null;
                if (_mod == null || _mod.Id != ModId)
                {
                    _mod = Item.LoadFromId(ModId, false, true, true, false);
                }
                return _mod;
            }
            set
            {
                if (value == null)
                    ModId = "0";
                else
                    ModId = value.Id;
                _mod = value;
                OnPropertyChanged("Mod");
            }
        }

        [XmlElement("EnhancementId")]
        public string _enhancementId;
        [XmlIgnore]
        public string EnhancementId
        {
            get { return _enhancementId ?? (_enhancementId = "0"); }
            set { _enhancementId = value; }
        }

        [XmlIgnore]
        private Item _enhancement;
        [XmlIgnore]
        public Item Enhancement
        {
            get
            {
                if (EnhancementId == "0") return null;
                if (_enhancement == null || _enhancement.Id != EnhancementId)
                {
                    _enhancement = Item.LoadFromId(EnhancementId, false, true, true, false);
                }
                return _enhancement;
            }
            set
            {
                if (value == null)
                    EnhancementId = "0";
                else
                    EnhancementId = value.Id;
                _enhancement = value;
                OnPropertyChanged("Enhancement");
            }
        }

        [XmlElement("ColorCrystalId")]
        public string _colorCrystalId;
        [XmlIgnore]
        public string ColorCrystalId
        {
            get { return _colorCrystalId ?? (_colorCrystalId = "0"); }
            set { _colorCrystalId = value; }
        }

        [XmlIgnore]
        private Item _colorCrystal;
        [XmlIgnore]
        public Item ColorCrystal
        {
            get
            {
                if (ColorCrystalId == "0") return null;
                if (_colorCrystal == null || _colorCrystal.Id != ColorCrystalId)
                {
                    _colorCrystal = Item.LoadFromId(ColorCrystalId, false, true, true, false);
                }
                return _colorCrystal;
            }
            set
            {
                if (value == null)
                    ColorCrystalId = "0";
                else
                    ColorCrystalId = value.Id;
                _colorCrystal = value;
                OnPropertyChanged("ColorCrystal");
            }
        }

        [XmlElement("AugmentId")]
        public string _augmentId;
        [XmlIgnore]
        public string AugmentId
        {
            get { return _augmentId ?? (_augmentId = "0"); }
            set { _augmentId = value; }
        }

        [XmlIgnore]
        private Item _augment;
        [XmlIgnore]
        public Item Augment
        {
            get
            {
                if (AugmentId == "0") return null;
                if (_augment == null || _augment.Id != HiltId)
                {
                    _augment = Item.LoadFromId(AugmentId, false, true, true, false);
                }
                return _augment;
            }
            set
            {
                if (value == null)
                    AugmentId = "0";
                else
                    AugmentId = value.Id;
                _augment = value;
                OnPropertyChanged("Augment");
            }
        }

        public ItemInstance GetItemInstance(Item item, int randomSuffixId, bool blacksmithingSocket)
        {
            if (item == null) return null;
            Item itemMod1 = null;
            Item itemMod2 = null;
            Item itemMod3 = null;
            Item itemMod4 = null;
            Item itemMod5 = null;
            switch (item.ItemArmoringHiltBarrelType)
            {
                case ItemSlot.Armoring: itemMod1 = Armoring; break;
                case ItemSlot.Barrel: itemMod1 = Barrel; break;
                case ItemSlot.Hilt: itemMod1 = Hilt; break;
                case ItemSlot.Mod: itemMod1 = Mod; break;
                case ItemSlot.Enhancement: itemMod1 = Enhancement; break;
                case ItemSlot.ColorCrystal: itemMod1 = ColorCrystal; break;
                case ItemSlot.Augment: itemMod1 = Augment; break;
                case ItemSlot.None:
                    if (blacksmithingSocket)
                    {
                        itemMod1 = Augment;
                        blacksmithingSocket = false;
                    }
                    break;
            }
            switch (item.ItemModType)
            {
                case ItemSlot.Armoring: itemMod2 = Armoring; break;
                case ItemSlot.Barrel: itemMod2 = Barrel; break;
                case ItemSlot.Hilt: itemMod2 = Hilt; break;
                case ItemSlot.Mod: itemMod2 = Mod; break;
                case ItemSlot.Enhancement: itemMod2 = Enhancement; break;
                case ItemSlot.ColorCrystal: itemMod2 = ColorCrystal; break;
                case ItemSlot.Augment: itemMod2 = Augment; break;
                case ItemSlot.None:
                    if (blacksmithingSocket)
                    {
                        itemMod2 = Augment;
                        blacksmithingSocket = false;
                    }
                    break;
            }
            switch (item.ItemEnhancementType)
            {
                case ItemSlot.Armoring: itemMod3 = Armoring; break;
                case ItemSlot.Barrel: itemMod3 = Barrel; break;
                case ItemSlot.Hilt: itemMod3 = Hilt; break;
                case ItemSlot.Mod: itemMod3 = Mod; break;
                case ItemSlot.Enhancement: itemMod3 = Enhancement; break;
                case ItemSlot.ColorCrystal: itemMod3 = ColorCrystal; break;
                case ItemSlot.Augment: itemMod3 = Augment; break;
                case ItemSlot.None:
                    if (blacksmithingSocket)
                    {
                        itemMod3 = Augment;
                        blacksmithingSocket = false;
                    }
                    break;
            }
            switch (item.ItemColorCrystalType)
            {
                case ItemSlot.Armoring: itemMod4 = Armoring; break;
                case ItemSlot.Barrel: itemMod4 = Barrel; break;
                case ItemSlot.Hilt: itemMod4 = Hilt; break;
                case ItemSlot.Mod: itemMod4 = Mod; break;
                case ItemSlot.Enhancement: itemMod4 = Enhancement; break;
                case ItemSlot.ColorCrystal: itemMod4 = ColorCrystal; break;
                case ItemSlot.Augment: itemMod4 = Augment; break;
                case ItemSlot.None:
                    if (blacksmithingSocket)
                    {
                        itemMod4 = Augment;
                        blacksmithingSocket = false;
                    }
                    break;
            }
            switch (item.ItemAugmentType)
            {
                case ItemSlot.Armoring: itemMod5 = Armoring; break;
                case ItemSlot.Barrel: itemMod5 = Barrel; break;
                case ItemSlot.Hilt: itemMod5 = Hilt; break;
                case ItemSlot.Mod: itemMod5 = Mod; break;
                case ItemSlot.Enhancement: itemMod5 = Enhancement; break;
                case ItemSlot.ColorCrystal: itemMod5 = ColorCrystal; break;
                case ItemSlot.Augment: itemMod5 = Augment; break;
                case ItemSlot.None:
                    if (blacksmithingSocket)
                    {
                        itemMod5 = Augment;
                        blacksmithingSocket = false;
                    }
                    break;
            }
            return new ItemInstance(item, randomSuffixId, itemMod1, itemMod2, itemMod3, itemMod4, itemMod5);
        }

        public override string ToString()
        {
            return string.Format("{0} # {1}: ({2}) A:{3} B:{4} H:{5} M:{6} E:{7} C:{8} A:{9}",
                Group, Id, Enabled ? "On" : "Off", ArmoringId, BarrelId, HiltId, ModId, EnhancementId, ColorCrystalId, AugmentId);
        }

        private static Dictionary<string, List<GemmingTemplate>> _allTemplates = new Dictionary<string, List<GemmingTemplate>>();
        public static Dictionary<string, List<GemmingTemplate>> AllTemplates
        {
            get { return _allTemplates; }
        }

        public static List<GemmingTemplate> GetModelTemplates(CalculationsBase model)
        {
            List<GemmingTemplate> list;
            if (!AllTemplates.TryGetValue(model.Name, out list))
            {
                list = new List<GemmingTemplate>(model.DefaultGemmingTemplates);
                AllTemplates[model.Name] = list;
            }
            return list;
        }

        public static List<GemmingTemplate> CurrentTemplates
        {
            get
            {
                return GetModelTemplates(Calculations.Instance);
            }
        }

        #region INotifyPropertyChanged Members
        private void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }
}
